package app

import (
  "common/config"
  "context"
  "fmt"
  "google.golang.org/grpc"
  "log"
  "net"
  "os"
  "os/signal"
  "syscall"
)

func Run(ctx context.Context) error {
  // start GRPC server
  server := grpc.NewServer()

  // 直接
  go func() {
    listen, err := net.Listen("tcp", config.Conf.Grpc.Addr)
    if err != nil {
      log.Fatalf("Failed to listen on %s: %v", config.Conf.Grpc.Addr, err)
    }
    // 因为Serve这里就是阻塞操作,如果不用协程,这里就会一直被阻塞, 下面的信号就无法监听了
    if err := server.Serve(listen); err != nil {
      log.Fatalf("Failed to serve: %v", err)
    }
  }()

  c := make(chan os.Signal, 1)
  signal.Notify(
    c,
    // 终止信号
    syscall.SIGTERM,
    // 退出信号
    syscall.SIGQUIT,
    // 中断信号
    syscall.SIGINT,
    // 挂断信号
    syscall.SIGHUP,
  )

  stop := func() {
    server.Stop()
    fmt.Println("stop app finish")
  }

  // 优雅启动停止
  for {
    select {
    case <-ctx.Done():
      return nil
    case sig := <-c:
      switch sig {
      case syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT:
        stop()
        log.Println("user app quit")
        return nil
      case syscall.SIGHUP:
        stop()
        log.Println("hang up user app quit")
        return nil
      default:
        return nil
      }
    }
  }
}
